using System;
using System.Collections.Generic;
using Dict.DataModel;
using Dict;

namespace Dict.Dao
{

    public abstract class DaoBase<T> where T : new()
    {

        protected List<T> cacheList;
        public List<T> CacheList
        {
            get
            {
                return cacheList;
            }
        }

        protected Dictionary<string, T> cachePrimary;

        public Dictionary<string, T> CachePrimary
        {
            get
            {
                return cachePrimary;
            }
        }

        protected Dictionary<string, List<T>> cacheOneIndex;

        public Dictionary<string, List<T>> CacheOneIndex
        {
            get
            {
                return cacheOneIndex;
            }
        }

        protected Dictionary<string, List<T>> cacheTwoIndex;

        public Dictionary<string, List<T>> CacheTwoIndex
        {
            get
            {
                return cacheTwoIndex;
            }
        }

        public static string GetUnionKey(string key1, string key2)
        {
            return key1+"|"+key2;
        }

        protected abstract T ParseRowData(string[] rowData);

        public virtual void LoadData(string path)
        {
            DictFileReader dfr = new DictFileReader(path + "/" + GetFileName());

            for (int i = 0; i < 5; ++i)
            {
                dfr.ReadRow();
            }
            string[] colStrs = dfr.ReadRow();
            cacheList = new List<T>();
            while (colStrs != null)
            {
                var model = ParseRowData(colStrs);
                if (model != null)
                {
                    cacheList.Add(model);
                }
                colStrs = dfr.ReadRow();
            }
            dfr.Dispose();
            BuildIndex();
        }

        public T GetById(string id)
        {
            if (!cachePrimary.ContainsKey(id))
            {
                return default(T);
            }
            return cachePrimary[id];
        }

        public T GetById(int id)
        {
            return GetById(id.ToString());
        }

        public List<T> GetByOneIndex(string index)
        {
            if (cacheOneIndex.ContainsKey(index))
            {
                return cacheOneIndex[index];
            }
            return new List<T>();
        }

        public List<T> GetByOneIndex(int index)
        {
            return GetByOneIndex(index.ToString());
        }

        public List<T> GetByTwoIndex(string index1, string index2)
        {
            string key = GetUnionKey(index1, index2);
            if (cacheTwoIndex.ContainsKey(key))
            {
                return cacheTwoIndex[key];
            }
            return new List<T>();
        }

        public List<T> GetByTwoIndex(int index1, int index2)
        {
            return GetByTwoIndex(index1.ToString(),index2.ToString());
        }

        public virtual void BuildIndex()
        {
            if (cacheList != null)
            {
                cachePrimary = new Dictionary<string, T>(cacheList.Count);
                cacheOneIndex = new Dictionary<string, List<T>>();
                cacheTwoIndex = new Dictionary<string, List<T>>();
                foreach (var model in cacheList)
                {
                    AddPrimaryIndex(model);
                    AddOneIndex(model);
                    AddTwoIndex(model);
                }
            }
        }

        public virtual void AddPrimaryIndex(T model)
        {

        }

        public virtual void AddOneIndex(T model)
        {

        }

        public virtual void AddTwoIndex(T model)
        {

        }

        public abstract string GetFileName();
    }
}
